package broth.gdt;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.pm.ActivityInfo;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;

public class MapTrackActivity extends MapActivity {
	
	MapView mapView;
	MyLocationOverlayCompass myLocation;
	CenterLocationOverlay centerLocationOverlay;
	MapController mapController;
	Location previous_location = null;
	GeoPoint geo_location;
	boolean start_track = false;
	boolean satellite_view = false;
	boolean hold_user_location = true;
	boolean satellite_mode = false;
	
	static final int DIALOG_STOP_TRACK = 0;
	
	// called when the activity is first created
	@Override
	public void onCreate(Bundle savedInstanceState) {
		
		// load the map track layout file
		super.onCreate(savedInstanceState);
		this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		setContentView(R.layout.maptrack);
		
		// get variable to the map view
		mapView = (MapView) findViewById(R.id.mapview);
		
		// configure map to use touch zoom controls only
		mapView.setBuiltInZoomControls(false);
		mapView.displayZoomControls(false);
		
		// set up an overlay to show location, compass heading, and accuracy
		myLocation = new MyLocationOverlayCompass(this, mapView, getResources());
		mapView.getOverlays().add(myLocation);
		
		// set up an overlay to animate to user location
		centerLocationOverlay = new CenterLocationOverlay(getResources(), this);
		mapView.getOverlays().add(centerLocationOverlay);
		
		// get a controller to move map center point and zoom level
		mapController = mapView.getController();
		
		// acquire a reference to the system Location Manager
		final LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
		
		// define a listener that responds to location updates
		LocationListener locationListener = new LocationListener() {
			// called when a new location is found by the network location provider
			public void onLocationChanged(Location location) {
				
				// if this is the first location update
				if(previous_location == null) {
					
					// record the location
					previous_location = new Location(location);
					
					// convert the location to a geopoint
					geo_location = new GeoPoint((int)(location.getLatitude()*Math.pow(10,6)),
							(int)(location.getLongitude()*Math.pow(10, 6)));
					
					// animate to this location and zoom to 18
					mapController.animateTo(geo_location);
					mapController.setZoom(18);
				}
				
				// if this is not the first location update
				else {
					
					// if the user has started a track
					if(start_track == true) {
						
						// add an overlay to the map showing the progress from the previous location
						mapView.getOverlays().add(new MapOverlay(
								(int)(previous_location.getLatitude()*Math.pow(10, 6)),
								(int)(previous_location.getLongitude()*Math.pow(10, 6)),
								(int)(location.getLatitude()*Math.pow(10, 6)),
								(int)(location.getLongitude()*Math.pow(10, 6))));
					}
					
					// if the user is holding location
					if(hold_user_location == true) {
						
						// animate the map to this new location
						mapController.animateTo(new GeoPoint(
								(int)(location.getLatitude()*Math.pow(10, 6)),
								(int)(location.getLongitude()*Math.pow(10, 6))));
					}
					
					// record the location
					previous_location.set(location);
				}
			}
			
			// handle for when a provider status changes
			public void onStatusChanged(String provider, int status, Bundle extras) {}
			
			// handle for when a provider is enabled
			public void onProviderEnabled(String provider) {}
			
			// handle for when a provider is disabled
			public void onProviderDisabled(String provider) {}
		};
		
		// register the listener with the Location Manager to receive location updates
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);

	}
	
	// create dialog with buttons
	protected Dialog onCreateDialog(int id) {
		Dialog dialog;
		
		// switch on dialog identifier
		switch(id) {
		
		// dialog for stopping track
		case DIALOG_STOP_TRACK:
			
			// build the dialog
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setMessage("Do you want to stop this track?")
			.setCancelable(false)
			
			// database is written and closed if "Yes" is selected
			.setPositiveButton("Yes", new OnClickListener() {
				public void onClick(DialogInterface dialog, int id) {
					start_track = false;
					/*try {
						// write track to database and close
					}
					catch (IOException e) {
						Log.w("MapTrackActivity", "IOException writing track to database on stop track");
					}*/
				}
			})
			
			// dialog is dismissed and no changes made if "No" is selected
			.setNegativeButton("No", new OnClickListener() {
				public void onClick(DialogInterface dialog, int id) {
					dialog.cancel();
				}
			});
			
			// dialog is created from builder
			AlertDialog dialog_stop_track = builder.create();
			
			// stop track dialog is returned
			return dialog_stop_track;
			
		default:
			dialog = null;
		}
		
		// default dialog (null) is returned
		return dialog;
	}
	
	// called to create the options menu
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		
		// result from superclass
		boolean result = super.onCreateOptionsMenu(menu);
		
		// inflate the menu from resources
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.maptrackmenu, menu);
		
		// return the superclass result
		return result;
	}
	
	// called when a menu item is selected
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		
		// switch on the selected item identifier
		switch(item.getItemId()) {
		
		// call handling functions based on the item selected
		case R.id.start_track:
			start_stop_track(item);
			return true;
			
		case R.id.view_tracks:
			view_tracks(item);
			return true;
			
		case R.id.gps_status:
			gps_status(item);
			return true;
			
		case R.id.satellite_view:
			satellite_view(item);
			return true;
		}
		
		// return the result of the superclass
		return super.onOptionsItemSelected(item);
	}
	
	// called to prepare the options menu
	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		
		// get the result from the super class
		boolean result = super.onPrepareOptionsMenu(menu);
		
		// if the track has not been started, set the start icon
		if(start_track == false) {
			menu.getItem(0).setIcon(android.R.drawable.ic_media_play);
			menu.getItem(0).setTitle(R.string.menu_start_track);
		}
		
		// return the result from the superclass
		return result;
	}
	
	// called when start/stop track menu item is selected
	private void start_stop_track(MenuItem item) {
		
		// if the track has not been started
		if(start_track == false) {
			
			// change the tracking status
			start_track = true;
			
			// set up the menu to show stop track item
			item.setIcon(android.R.drawable.ic_media_pause);
			item.setTitle(R.string.menu_stop_track);
			
			// prepare a short toast to indicate that the track has started
			CharSequence start_text = "Starting track.";
			int duration = Toast.LENGTH_SHORT;
			Toast toast = Toast.makeText(this, start_text, duration);
			toast.show();
		}
		
		// if the track is being stopped
		else {
			
			// show the dialog confirming the tracking stop
			showDialog(DIALOG_STOP_TRACK);
		}
	}
	
	// called when view tracks menu item is selected
	private void view_tracks(MenuItem item) {
		
		// prepare a short toast to indicate that this function is not implemented
		CharSequence text = "View Tracks is not yet implemented.";
		int duration = Toast.LENGTH_SHORT;
		Toast toast = Toast.makeText(this, text, duration);
		toast.show();
	}
	
	// called when gps status menu item is selected
	private void gps_status(MenuItem item) {
		
		// prepare a short toast to indicate that this function is not implemented
		CharSequence text = "Gps Status is not yet implemented.";
		int duration = Toast.LENGTH_SHORT;
		Toast toast = Toast.makeText(this, text, duration);
		toast.show();
		
		//#FIXME remove comment braces when GpsStatusActivity is created
		/*Intent intent = new Intent(this, GpsStatusActivity.class);
		startActivity(intent);*/
	}
	
	// called when map/satellite view menu item is selected
	private void satellite_view(MenuItem item) {
		
		// if in map mode
		if(satellite_mode == false) {
			
			// go to satellite mode
			satellite_mode = true;
			
			// set menu item title to map view
			item.setTitle(R.string.menu_map_view);
		}
		
		// if in satellite mode
		else {
			
			// go to map mode
			satellite_mode = false;
			
			// set menu item title to satellite view
			item.setTitle(R.string.menu_satellite_view);
		}
		
		// configure the map to show selected view
		mapView.setSatellite(satellite_mode);
	}
	
	// called to center the map on the users location
	public void center_user_location() {
		
		// if the location compass is enabled
		if(myLocation.isMyLocationEnabled()) {
			
			// center the map on the location known to the location compass
			mapController.animateTo(myLocation.getMyLocation());
			mapController.setZoom(18);
		}
		
		// if the location compass is disabled, but the listener has a point
		else if(previous_location != null) {
			
			// create a geopoint with the location
			geo_location = new GeoPoint(
					(int)(previous_location.getLatitude()*Math.pow(10, 6)),
					(int)(previous_location.getLongitude()*Math.pow(10, 6)));
			
			// center the map on the location and set the zoom level to 18
			mapController.animateTo(geo_location);
			mapController.setZoom(18);
		}
		
		// hold the users location
		hold_user_location = true;
	}
	
	// called to stop holding the users location
	public void drop_user_location() {
		hold_user_location = false;
	}

	// required maps function that indicates no route is being displayed
	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}
	
	// called when activity is resumed
	@Override
	public void onResume() {
		
		// superclass resume
		super.onResume();
		
		// log the resume
		Log.i("MapTrackActivity", "MapTrackActivity resumed");
		
		// enable the location listener and compass sensors
		myLocation.enableMyLocation();
		myLocation.enableCompass();
	}
	
	// called when activity is paused
	@Override
	public void onPause() {
		
		// superclass pause
		super.onPause();
		
		// log the pause
		Log.i("MapTrackActivity", "MapTrackActivity paused");
		
		// disable the location listener and compass sensors (saves power)
		myLocation.disableMyLocation();
		myLocation.disableCompass();
	}
	
}
